package com.wolfsea.pagerecyclerviewdemo;
import android.content.Context;
import android.graphics.Rect;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;

/**
 * @author liuliheng
 * @desc HorizontalPageLayoutManager
 * @time 2023/1/7  23:47
 **/
public class HorizontalPageLayoutManager extends RecyclerView.LayoutManager implements PageDecorationLastJudge {

    public static final String TAG = "HorizontalPageLayoutManager";

    int totalWidth = 0;
    int offsetY = 0;
    int offsetX = 0;

    int rows;
    int columns;
    int pageSize = 0;
    int onePageSize;

    private final SparseArray<Rect> allItemFrames;
    private final Context context;

    public HorizontalPageLayoutManager(Context context, int rows, int columns) {
        this.context = context;
        this.rows = rows;
        this.columns = columns;
        this.onePageSize = rows * columns;
        allItemFrames = new SparseArray<>();
    }

    @Override
    public void onAttachedToWindow(RecyclerView view) {
        super.onAttachedToWindow(view);
    }

    @Override
    public RecyclerView.LayoutParams generateDefaultLayoutParams() {
        return null;
    }

    @Override
    public boolean canScrollHorizontally() {
        return true;
    }

    @Override
    public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
        detachAndScrapAttachedViews(recycler);
        int newX = offsetX + dx;
        int result = dx;
        if (newX > totalWidth) {
            result = totalWidth - offsetX;
        } else if (newX < 0) {
            result = -offsetX;
        }
        offsetX += result;
        offsetChildrenHorizontal(-result);
        recycleAndFillItems(recycler, state);
        return result;
    }

    @Override
    public int computeHorizontalScrollRange(RecyclerView.State state) {
        computePageSize(state);
        return pageSize * getWidth();
    }

    @Override
    public int computeHorizontalScrollOffset(RecyclerView.State state) {
        return offsetX;
    }

    @Override
    public int computeHorizontalScrollExtent(RecyclerView.State state) {
        return getWidth();
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        if (getItemCount() == 0) {
            removeAndRecycleAllViews(recycler);
            return;
        }

        if (state.isPreLayout()) {
            return;
        }

        //计算总的页数
        computePageSize(state);
        Log.d(TAG, "itemCount=" + getItemCount() + " state itemCount=" + state.getItemCount() + " pageSize=" + pageSize);
        //计算可以横向滚动的最大值
        totalWidth = (pageSize - 1) * getWidth();

        //分离view
        detachAndScrapAttachedViews(recycler);

        int itemCount = getItemCount();
        int totalItemWidth = 0;
        int totalItemHeight = 0;
        int pageWidth = 0;

        for (int i = 0; i < itemCount; i++) {
            View view = recycler.getViewForPosition(i);
            //添加itemView
            addView(view);
            //测量item
            measureChildWithMargins(view, 0, 0);
            int width = getDecoratedMeasuredWidth(view);
            int height = getDecoratedMeasuredHeight(view);
            //记录显示范围
            Rect rect = allItemFrames.get(i);
            if (rect == null) {
                rect = new Rect();
            }

            float remainedWidth = getWidth() - width * columns;
            int itemSpace = (int) (remainedWidth / (columns + 1));

            int left = itemSpace + totalItemWidth + pageWidth;
            int right = left + width;
            int topSpace = (int) context.getResources().getDimension(R.dimen.dp_20);
            int top = topSpace + totalItemHeight;
            int bottom = top + height;
            rect.set(left, top, right, bottom);
            allItemFrames.put(i, rect);

            totalItemWidth += itemSpace + width;
            if ((i + 1) % columns == 0) {
                totalItemWidth = 0;
                totalItemHeight += topSpace + height;
            }

            if ((i + 1) % (columns * rows) == 0) {
                pageWidth += getWidth();
                totalItemHeight = 0;
                //每一页循环以后就回收一页的View用于下一页的使用
                //removeAndRecycleAllViews(recycler);
            }
            //每用完一个view就回收一个
            removeAndRecycleView(view, recycler);
        }
        recycleAndFillItems(recycler, state);
    }

    @Override
    public void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) {
        super.onDetachedFromWindow(view, recycler);
        offsetX = 0;
        offsetY = 0;
    }

    @Override
    public boolean isLastRow(int index) {
        if (index >= 0 && index < getItemCount()) {
            int indexOfPage = index % onePageSize;
            indexOfPage++;
            if (indexOfPage > (rows - 1) * columns && indexOfPage <= onePageSize) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean isLastColumn(int position) {
        if (position >= 0 && position < getItemCount()) {
            position++;
            if (position % columns == 0) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean isPageLast(int position) {
        position++;
        return position % onePageSize == 0;
    }

    private void recycleAndFillItems(RecyclerView.Recycler recycler, RecyclerView.State state) {
        if (state.isPreLayout()) {
            return;
        }
        Rect displayRect =
                new Rect(
                        getPaddingLeft() + offsetX,
                        getPaddingTop(),
                        getWidth() - getPaddingLeft() - getPaddingRight() + offsetX,
                        getHeight() - getPaddingTop() - getPaddingBottom()
                );
        Rect childRect = new Rect();
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (child != null) {
                childRect.left = getDecoratedLeft(child);
                childRect.top = getDecoratedTop(child);
                childRect.right = getDecoratedRight(child);
                childRect.bottom = getDecoratedBottom(child);
                if (!Rect.intersects(displayRect, childRect)) {
                    removeAndRecycleView(child, recycler);
                }
            }
        }

        for (int i = 0; i < getItemCount(); i++) {
            if (Rect.intersects(displayRect, allItemFrames.get(i))) {
                View view = recycler.getViewForPosition(i);
                //添加itemView
                addView(view);
                //测量itemView
                measureChildWithMargins(view, 0, 0);
                Rect rect = allItemFrames.get(i);
                layoutDecorated(
                        view,
                        rect.left - offsetX,
                        rect.top,
                        rect.right - offsetX,
                        rect.bottom
                );
            }
        }
    }

    private void computePageSize(RecyclerView.State state) {
        pageSize = state.getItemCount() / onePageSize + (state.getItemCount() % onePageSize == 0 ? 0 : 1);
    }

}

